import {ElMessageBox} from "element-plus/es";
import {AxiosResponse} from "axios";
import MsgUtils from "@/common/utils/MsgUtils";


declare type MessageType = 'success' | 'warning' | 'info' | 'error';


export class Request<R> {
    // @ts-ignore
    //执行的http请求方法
    private httpFunc = (): Promise<AxiosResponse<any>> => {
    };
    private confirmObj?: ConfirmObj;
    private startDoing = () => {
        //执行开始
    }
    private endDoing = () => {
        //执行结束
    }
    private successFunc = (result: R) => {
        //成功的回调
    };
    //失败的回调,默认未知错误
    private errorFunc = (msg: string) => {
        //失败的回调
    };

    public setHttp<R>(doHttpFunc: () => any) {
        this.httpFunc = doHttpFunc;
        return this;
    }


    public confirm(msg: string, title?: string, type?: 'success' | 'warning' | 'info' | 'error') {
        this.confirmObj = new ConfirmObj();
        this.confirmObj.confirmMsg = msg;
        this.confirmObj.confirmTitle = title;
        this.confirmObj.confirmType = type;
        return this;
    }

    //网络开始的时候执行
    public start(startDoing: () => any) {
        this.startDoing = startDoing;
        return this;
    }

    //网络结束的时候执行
    public end(endDoing: () => any) {
        this.endDoing = endDoing;
        return this;
    }


    public successMsg(msgText: (result: R) => string) {
        this.successFunc = (result: R) => {
            MsgUtils.successMsg(msgText(result))
        };
        return this;
    }

    public errorMsg(msg: string) {
        this.errorFunc = (msg: string) => {
            MsgUtils.errorNotify(msg)
        };
        return this;
    }

    public success(successFunc: (result: R) => any) {
        this.successFunc = successFunc;
        return this;
    }

    public error(errorFunc: (msg: string) => any) {
        this.errorFunc = errorFunc;
        return this;
    }


    //正常请求
    public async request() {
        //判断是否弹窗
        if (this.confirmObj && !await this.confirmObj.isConfirmed()) {
            return;
        }
        this.startDoing();
        await this.httpFunc().then(value => {
            //成功或者失败的回调
            if (value.data.success === true) {
                this.successFunc(value.data);
            } else {
                this.errorFunc(value.data.msg);
            }
        }).catch(reason => {
            console.log(reason)
            this.errorFunc('系统错误');
        });
        this.endDoing();
    }

    //下载文件
    public async download(fileName: string) {
        //判断是否弹窗
        if (this.confirmObj && !await this.confirmObj.isConfirmed()) {
            return;
        }
        this.startDoing();
        await this.httpFunc().then(value => {
            this.result2File(value, fileName);
            this.successFunc(value.data);
        }).catch(reason => {
            this.errorFunc('系统错误');
        });
        this.endDoing();
    }

    //将返回的文件流转换为文件
    private result2File(value: any, fileName: string) {
        const blob = new Blob([value.data], {type: value.headers['content-type']});
        const downloadElement = document.createElement('a');
        const href = window.URL.createObjectURL(blob); //创建下载的链接
        downloadElement.href = href;
        downloadElement.download = fileName; //下载后文件名
        document.body.appendChild(downloadElement);
        downloadElement.click(); //点击下载
        document.body.removeChild(downloadElement); //下载完成移除元素
        window.URL.revokeObjectURL(href); //释放掉blob对象
    }
}


export class ConfirmObj {
    //确认弹窗的内容
    public confirmMsg!: string;
    //确认弹窗的标题,默认 确认操作
    public confirmTitle?: string;
    //确认弹窗的类型,默认 info
    public confirmType?: MessageType;

    public async isConfirmed() {
        let confirm = true;
        await ElMessageBox.confirm(this.confirmMsg, this.confirmTitle ? this.confirmTitle : '确认操作', {
            confirmButtonText: '确认', cancelButtonText: '取消', type: this.confirmType ? this.confirmType : 'info',
        }).then((res) => {
            confirm = (res === 'confirm');
        }).catch(reason => {
            confirm = false;
        });
        return confirm;
    }
}